#include <stdio.h>
#include <string.h>
#define MASK2 (0x00000003)
#define MASK4 (0x0000000f)
#define MASK8 (0x000000ff)
#define MODEL_OFFSET 4
#define FAMILY_ID_OFFSET 8
#define PROCESSOR_TYPE 12
#define EXTENDED_MODEL_ID 16
#define EXTENDED_FAMILY_ID 20
typedef unsigned int uint32_t;

struct cpuid_info{
    uint32_t eax;
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;
};
void get_cpuinfo(uint32_t eax, uint32_t ecx, struct cpuid_info* cpuid) {
    asm(
            "cpuid":
            "=a"(cpuid->eax), "=b"(cpuid->ebx), "=c"(cpuid->ecx), "=d"(cpuid->edx):
            "a"(eax), "c"(ecx)
       );
}
char cpu_ID[13];
void get_vendor_ID(char* vendorID) {
    struct cpuid_info cpuinfo;
    get_cpuinfo(0, 0, &cpuinfo);
    strncpy(vendorID, (const char*)&cpuinfo.ebx, 4);
    strncpy(vendorID+4, (const char*)&cpuinfo.edx, 4);
    strncpy(vendorID+8, (const char*)&cpuinfo.ecx, 4);
    vendorID[13] = '\0';
}
void get_processinfo_and_features() {
    struct cpuid_info cpuid;
    get_cpuinfo(1, 0, &cpuid);
//    printf("eax, ebx, ecx, edx: %08x, %08x, %08x, %08x\n", cpuid.eax, cpuid.ebx, cpuid.ecx, cpuid.edx);
    int eax = cpuid.eax;
    printf("Stepping ID: %d\n", (eax)&(MASK4));
    printf("Model: %d\n", (eax>>MODEL_OFFSET)&(MASK4));
    printf("Family ID: %d\n", (eax>>FAMILY_ID_OFFSET)&(MASK4));
    printf("Process Type: %d\n", (eax>>PROCESSOR_TYPE)&(MASK2));
    printf("Extend Model ID: %d\n", (eax>>EXTENDED_MODEL_ID)&(MASK4));
    printf("Extend Family ID: %d\n", (eax>>EXTENDED_FAMILY_ID)&(MASK8));
}

int main(int argc, char** argv) {
    int i;
    get_vendor_ID(cpu_ID);
    printf("vendor ID: %s\n", cpu_ID);
    get_processinfo_and_features();
    return 0;
}
